import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;


public class ROCData 
{
	private DistanceMatrix _distMat;
	private static final int ROC_BINS	= 1000;
	
	
	
	double _vals[];
	double _matchPortion[];
	double _mismatchPortion[];
	
	public ROCData(DistanceMatrix distMat)
	{
		_distMat = distMat;
		calcROC();
	}
	
	public void storeToFile(File f) throws IOException
	{
		// Ok, I now have the data ready for a ROC-Plot			
		
		BufferedWriter bw = new BufferedWriter(new FileWriter(f));

		// column description
		bw.append("Distance, Matches, Mismatches");
		bw.newLine();
		
		for (int i = 0; i < _vals.length; i++)
		{
		
			bw.append(_vals[i] + "," + _matchPortion[i] + "," + _mismatchPortion[i]);
			bw.newLine();
		}

		bw.flush();
		bw.close();
	}
	
	private void calcROC()
	{
		_vals = new double[ROC_BINS];
		_matchPortion = new double[ROC_BINS];
		_mismatchPortion = new double[ROC_BINS];
		
		int[] match_freq = new int[ROC_BINS];			// split into 1000 elements
		int[] mismatch_freq = new int[ROC_BINS];

		int matchCnt = 0;
		int mismatchCnt = 0;

		
		// run over current distance matrix and compute distribution on matches/mismatches upon the parameter i
		for(int x=0; x<_distMat.getWidth(); x++)
		{
			for(int y=0; y<_distMat.getHeight(); y++)
			{
				// index calculates by ROC-Resolution
				int idx = (int) (_distMat.distAt(x, y) * ROC_BINS);
				
				if(_distMat.isMatchAt(x, y))
				{
					match_freq[idx]++;
					matchCnt++;
				}
				else
				{
					mismatch_freq[idx]++;
					mismatchCnt++;
				}
			}
		}
		
		// Ok, I now have the data ready for a ROC-Plot					
				
		for (int i = 0; i < match_freq.length; i++)
		{
			_vals[i] = (double) i / ROC_BINS;
			_matchPortion[i] = (double) match_freq[i] / (double) matchCnt;
			_mismatchPortion[i] = (double) mismatch_freq[i] / (double) mismatchCnt;			
		}		
	}
	
	private double integrateTo(int idx, double[] arr)
	{
		double sum = 0;
		for(int i=0; i<idx; i++)
		{
			sum += arr[i];
		}
		
		return sum;
	}
	
	public double getOptimiumThres()
	{
		
		int idx_min = -1;
		double curMin = 0.0;
		
		for (int i = 0; i < _vals.length; i++)
		{
			double matchArea = integrateTo(i, _matchPortion);
			double mismatchArea = integrateTo(i, _mismatchPortion);
			
			double ratio = matchArea / (mismatchArea + 0.00001);
			
			if(ratio > curMin)
			{
				curMin = ratio;
				idx_min = i;
			}
			
		}
		
		return (double)idx_min / (double)ROC_BINS;
	}
}
